package com.alorm.utils;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.content.Context;
import android.util.Log;

import com.alorm.core.exceptions.AlormException;
import com.alorm.core.exceptions.MappingException;
import com.alorm.core.sqlite.annotation.EntityClass;
import com.alorm.core.sqlite.annotation.Id;
import com.alorm.core.sqlite.sqlgen.Conversion;

import dalvik.system.DexFile;

public class AlormUtils {

	public static String getClassName(Class pClass) {

		String[] tokens = pClass.getName().trim().split("\\.");

		return tokens[tokens.length - 1];

	}

	public static String getPkName(Class pClass) {

		String fNom = null;
		Field[] fields = pClass.getDeclaredFields();
		for (Field it : fields) {
			Id id = it.getAnnotation(Id.class);
			if (id != null)
				fNom = it.getName();
		}
		if (fNom == null)
			throw new MappingException(
					"Erreur de mapping, il n'existe aucun attribut  dans la classe ayant l'annotation @Id.");

		Log.i("test", fNom);
		return fNom;
	}

	public static String getPkType(Class pClass) {
		Field field = null;

		Field[] fields = pClass.getDeclaredFields();
		for (Field it : fields) {
			Id id = it.getAnnotation(Id.class);
			if (id != null)
				field = it;
		}

		Conversion conver = Conversion.getConversion();

		String fType = conver.getTypeSQL(getClassName(field.getType()));
		return fType;
	}

	public static String getGetterMethod(String pFieldName) {

		char majChar = Character.toUpperCase(pFieldName.charAt(0));

		return "get" + majChar + pFieldName.substring(1);

	}

	public static Map<String, String> getAllFieldsValue(Object pObject,
			List listClassPer) throws NoSuchMethodException, SecurityException,
			IllegalAccessException, IllegalArgumentException,
			InvocationTargetException {

		Class lClass = pObject.getClass();
		Map<String, String> fieldsValue = new HashMap<String, String>();
		Field fields[] = lClass.getDeclaredFields();
		String fieldName;
		Class fieldClass;
		Method method = null;
		Object val = null;
		// number = (Number)

		for (int i = 1; i < fields.length; i++) {
			fieldName = fields[i].getName();
			fieldClass = fields[i].getType();

			if (!fieldClass.equals(ArrayList.class)) {

				method = lClass.getMethod(getGetterMethod(fieldName));
				val = method.invoke(pObject);

				if (!listClassPer.contains(fieldClass)) {
					if (val.getClass().equals(String.class))
						val = "'" + val + "'";

				} else {
					String pkName = getPkName(fieldClass);
					method = fieldClass.getMethod(getGetterMethod(pkName));
					if (val != null)
						val = method.invoke(val);

				}

				fieldsValue.put(fields[i].getName(), String.valueOf(val));

			}
		}

		return fieldsValue;
	}

	public static String getClassName(Type pType) {

		String[] tokens = pType.toString().trim().split("\\.");

		return tokens[tokens.length - 1];

	}

	public static String getClass(Type pType) {

		String[] tokens = pType.toString().trim().split(" ");

		return tokens[1];

	}

	public static ArrayList<Class> getListClassPer(Context context) {

		ArrayList<Class> listClassPer = new ArrayList<Class>();

		try {
			DexFile dex = new DexFile(context.getApplicationInfo().sourceDir);
			ClassLoader classLoader = Thread.currentThread()
					.getContextClassLoader();
			Enumeration<String> entries = dex.entries();
			while (entries.hasMoreElements()) {
				String entry = entries.nextElement();
				if (classLoader.loadClass(entry).isAnnotationPresent(
						EntityClass.class))
					listClassPer.add(classLoader.loadClass(entry));
			}
		} catch (Exception e) {
			throw new AlormException(e);
		}

		return listClassPer;
	}

}
